#define ESC 0X1B
#define PORT1 0x3F8  /* Defines Serial Port Base Address (COM1 */
#include <windows.h>
#include <string>
using namespace std;

HANDLE hCom;           //handle for serial port I/O

/*----------------------------------------------------------------------------*
 * Serial port: initialise io_port, set baud rate, set data bits, one stop bit*/

HANDLE rs_initialise (string io_port, const long int BaudRate, const char parity, const char data)
{
    BOOL bPortReady;
    DCB dcb;
	    COMMTIMEOUTS CommTimeouts;

    char ComPortName[20];           // set up COM port number in COM?
//   ComPortName[10]=io_port;
    strcpy(ComPortName,io_port.c_str());    

    hCom = CreateFile(ComPortName, GENERIC_READ | GENERIC_WRITE,
                                  0,            // exclusive access
                                  NULL,         // no security
                                  OPEN_EXISTING,
                                  0,            // no overlapped I/O
                                  NULL);        // null template
                                  
  
    if ((int)hCom <= 0) { printf("serial port %s connect fail %s error %d\n\r", io_port.c_str(), ComPortName, GetLastError()); return 0;   } 
    //else                printf(" serial port COM%d connect OK \n\r", io_port); 
                 
    bPortReady = SetupComm(hCom, 2, 128); // set buffer sizes
    if (!bPortReady ) { printf("serial port %s SetupComm fail  %d\n\r", io_port.c_str(),  GetLastError()); return 0;   } 
    //else                printf(" serial port COM%d connect OK \n\r", io_port); 

    bPortReady = GetCommState(hCom, &dcb);
    if (!bPortReady ) { printf("serial port %s  GetCommState fail  %d\n\r", io_port.c_str(),  GetLastError()); return 0;   } 
  //  else                printf(" serial port COM%d connect OK \n\r", io_port); 
    dcb.BaudRate = BaudRate;
    if( data == '7') dcb.ByteSize = 7;
    else             dcb.ByteSize = 8;
    if( parity == 'E') dcb.Parity = EVENPARITY;
    if( parity == 'O') dcb.Parity = ODDPARITY;
    else               dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.fAbortOnError = TRUE;

    // set XON/XOFF
    dcb.fOutX = FALSE;                       // XON/XOFF off for transmit
    dcb.fInX = FALSE;                        // XON/XOFF off for receive
    // set RTSCTS
    dcb.fOutxCtsFlow = FALSE;               // turn off CTS flow control
    dcb.fRtsControl = FALSE;                // RTS_CONTROL_HANDSHAKE; //
    // set DSRDTR
    dcb.fOutxDsrFlow = FALSE;               // turn off DSR flow control
    //dcb.fDtrControl = DTR_CONTROL_ENABLE; // DTR handshake
    dcb.fDtrControl = DTR_CONTROL_DISABLE;  //
    // dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; //

    bPortReady = SetCommState(hCom, &dcb);
    if (!bPortReady ) { printf("serial port %s  SetCommState fail  %d\n\r", io_port.c_str(),  GetLastError()); return 0;   } 

    // Communication timeouts 
    //COMMTIMEOUTS CommTimeouts;
    bPortReady = GetCommTimeouts (hCom, &CommTimeouts);
    CommTimeouts.ReadIntervalTimeout = 5 ;
    CommTimeouts.ReadTotalTimeoutConstant = 5 ;
    CommTimeouts.ReadTotalTimeoutMultiplier = 1 ;
    CommTimeouts.WriteTotalTimeoutConstant = 5 ;
    CommTimeouts.WriteTotalTimeoutMultiplier = 1 ;
    bPortReady = SetCommTimeouts (hCom, &CommTimeouts);
    if (!bPortReady ) { printf("serial port %s SetCommTimeouts fail  %d\n\r", io_port.c_str(),  GetLastError()); return 0;   } 
    else                printf(" serial port %s connect OK \n\r", io_port.c_str()); 
    return hCom;
}

/*----------------------------------------------------------------------------*
 * Serial port:  initialise using command line parameters passed from main()  *
 *  return serial port value in range 0 to 3 of all OK                        */
int rs_parameters(int argc, char *argv[], const int print_data)
{
    int io_port = 1, parity = 'n', data = '8';
    long int baud_rate = 9600l; 
    char *chr_ptr;
    int index;

    /* search command line for port number, baud rate, etc. */
    for (index = 0; index < argc ; index++)
       {
       if ((chr_ptr = strstr(argv[index],"port=com")) != 0)
          {
          chr_ptr = chr_ptr + 8;           /* found port=com, point to number */
          io_port = (int) strtol(chr_ptr, NULL, 10);        /* convert number */
          }
       if ((chr_ptr = strstr(argv[index],"baud=")) != 0)
          {
      chr_ptr = chr_ptr + 5;              /* found baud=, point to number */
          baud_rate = strtol(chr_ptr, NULL, 10);            /* convert number */
          }
       if ((chr_ptr = strstr(argv[index],"parity=")) != 0)
          parity = *(chr_ptr + 7);                 /* found parity=, get char */
       if ((chr_ptr = strstr(argv[index],"data=")) != 0)
          data = *(chr_ptr + 5);              /* found data lenngth, get char */
    }

    if (print_data)
      {
      printf("\nRS232 serial line initialisation \n"
           "  command line options: port=com1/2/3/4\n"
       "                        baud=2400/4800/9600/19200"
                                    "/38400/57600/115200\n"
           "                        parity=n/e/o\n"
           "                        data=7/8\n\n"
           "  initialising port = com%d,", io_port);
      printf(" baud rate = %ld, parity = %c, data = %c\n\n", 
                         baud_rate, parity, data);
      }
    io_port = io_port - 1;
//    rs_initialise(io_port, baud_rate, parity, data);          /* initialise io_port */
    return io_port;
}

/*----------------------------------------------------------------------------*
 * Serial port: terminate io_port, sets DTR and RTS to low                     */
void rs_terminate(const int io_port)
{
  // Close(hCom);
}



/*----------------------------------------------------------------------------*
 * Serial port: read character from io_port (ignored in this version)         */
unsigned char rs_getch()
{
    unsigned char rxchar;
    BOOL bReadRC;
    static DWORD iBytesRead;
    bReadRC = ReadFile(hCom, &rxchar, 1, &iBytesRead, NULL);
    if (iBytesRead) return rxchar; else return 0;         // return 0 if no character read
}

/*----------------------------------------------------------------------------*
 * Serial port: transmit character to io_port                                 */
//void rs_putch(const int io_port, const int txchar)
void rs_putch(const int txchar)
{
    BOOL bWriteRC;
    static DWORD iBytesWritten;
    bWriteRC = WriteFile(hCom, &txchar, 1, &iBytesWritten,NULL);
    return;
}

/*----------------------------------------------------------------------------*
 * Serial port: transmit a string of characters to io_port                    */
void rs_putstring(const int io_port, const char *string)
{
    while (*string != '\0')
        rs_putch(*string++);
}
